package com.movie.service;

import com.movie.dto.UserRatingDTO;
import com.movie.entity.UserRating;
import com.movie.entity.User;
import com.movie.entity.Movie;
import com.movie.repository.UserRatingRepository;
import com.movie.repository.UserRepository;
import com.movie.repository.MovieRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.Flow;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class UserRatingService {

    private final UserRatingRepository userRatingRepository;
    private final UserRepository userRepository;
    private final MovieRepository movieRepository;

    // 添加或更新评分
    @Transactional
    public UserRatingDTO addOrUpdateRating(Long userId, Long movieId, Double rating, String comment) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        Movie movie = movieRepository.findById(movieId)
                .orElseThrow(() -> new RuntimeException("电影不存在"));

        // 验证评分范围
        if (rating < 1 || rating > 5) {
            throw new RuntimeException("评分必须在1-5之间");
        }

        Optional<UserRating> existing = userRatingRepository.findByUserAndMovie(user, movie);
        UserRating userRating;

        if (existing.isPresent()) {
            userRating = existing.get();
            userRating.setRating(rating);
            userRating.setComment(comment);
        } else {
            userRating = new UserRating();
            userRating.setUser(user);
            userRating.setMovie(movie);
            userRating.setRating(rating);
            userRating.setComment(comment);
        }

        UserRating saved = userRatingRepository.save(userRating);
        return convertToDTO(saved);
    }

    // 删除评分
    @Transactional
    public void removeRating(Long userId, Long movieId) {
        if (!userRatingRepository.existsByUser_IdAndMovie_Id(userId, movieId)) {
            throw new RuntimeException("评分记录不存在");
        }
        userRatingRepository.deleteByUser_IdAndMovie_Id(userId, movieId);
    }

    // 获取用户评分列表
    public List<UserRatingDTO> getUserRatings(Long userId) {
        return userRatingRepository.findByUser_Id(userId).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public UserRatingDTO getUserRatings(Long userId, Long movieId) {
        return convertToDTO(userRatingRepository.findByUser_IdAndMovie_Id(userId, movieId)
        );
    }

    // 获取电影评分列表
    public List<UserRatingDTO> getMovieRatings(Long movieId) {
        return userRatingRepository.findByMovie_Id(movieId).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    // 检查用户是否评过分
    public boolean hasRated(Long userId, Long movieId) {
        return userRatingRepository.existsByUser_IdAndMovie_Id(userId, movieId);
    }

    // 获取用户对某部电影的评分
    public Optional<UserRatingDTO> getUserRatingForMovie(Long userId, Long movieId) {
        return userRatingRepository.findByUserAndMovie(
                userRepository.findById(userId).orElse(null),
                movieRepository.findById(movieId).orElse(null)
        ).map(this::convertToDTO);
    }

    // 计算电影平均评分
    public Double calculateMovieAverageRating(Long movieId) {
        return userRatingRepository.calculateAverageRatingByMovieId(movieId);
    }

    // 统计电影评分数量
    public long countMovieRatings(Long movieId) {
        return userRatingRepository.countByMovie_Id(movieId);
    }

    private UserRatingDTO convertToDTO(UserRating rating) {
        if (rating == null) {
            return null;
        }
        UserRatingDTO dto = new UserRatingDTO();
        dto.setId(rating.getId());
        dto.setUserId(rating.getUser().getId());
        dto.setUsername(rating.getUser().getUsername());
        dto.setMovieId(rating.getMovie().getId());
        dto.setMovieTitle(rating.getMovie().getTitle());
        dto.setMovieCover(rating.getMovie().getCover());
        dto.setRating(rating.getRating());
        dto.setComment(rating.getComment());
        dto.setCreatedAt(rating.getCreatedAt());
        dto.setUpdatedAt(rating.getUpdatedAt());
        return dto;
    }
}